//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
//
//	File		 :	FormattedOutput.h
//	Contents	 :	Source file for class CFormattedOutput
//	Creation Date:	22/12/1999
//	Last Modified:	23/12/1999	lg
//	tabs width	 :	every 4 characters

//
//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888

#if !defined(FORMATTEDOUTPUT_H)
#define FORMATTEDOUTPUT_H

#include <map>
#include <vector>
#include <string>
#include <cassert>
#include <map>
#ifdef _MFC_VER
#include "msword9.h"
#endif

#ifdef _MFC_VER	// mfc specific code to follow
#include "mfc_stdcpp.h"
#else
#include "nonmfc_stdcpp.h"
#endif


//_______________________________________________________________________________________
//
//	CFormattedOutput
//
//		virtual base class for producing formatted text
//
//		Generally, the only necessary function calls are (in order):
//
//			1) AddFormat/AddFormats:
//				adds all the text formats which will be used throughout
//
//			2) BeginHeader()
//
//			3) AddText, AddNewLine
//			   SetFormat
//				switches to one of the formats from AddFormat(s)
//
//			5) EndFooter()
//
//			6) 	CopytoClipboard() or
//				GetStreamedText() or
//				CopyToWord()
//
//
//				[ AddToWordDocument()
//					is commented out pending further testing etc.]
//
//
//		Implementation:
//			For performance reasons, text is added to a queue
//			 which is flushed only on format change, new line or at the end
//
//_______________________________________________________________________________________
// conditional definition for non window builds

class CFormattedOutput
{
public:
	struct CTextFormat;
								// NB text size is specified in tenths of a point
								CFormattedOutput(unsigned textSize10ths = 100,
											const std::string& textFont = "Courier New");
	virtual						~CFormattedOutput(){}

// inlines
	// formats
	void						AddFormat(const CTextFormat&);
	void						AddFormats(const std::vector<CTextFormat>& vec);
	void						ClearFormats();
	const CTextFormat&			GetFormat(unsigned i);
	unsigned						GetFormatsCount();
	unsigned						GetFormatsTableSize();
	const std::vector<CTextFormat>&
								GetFormatsTable();

	// add text
	void						AddText(const std::string& s);
	void						AddText(const std::string& s, unsigned pos, unsigned len);
	void						AddText(char s);
	// progress
	bool						IsInProgress();

// operations
	void						BeginHeader();
	void						EndFooter();
	void						SetFormat(unsigned index);

	// virtual functions: overrride to provide functionality
	virtual void				AddNewLine()					= 0;
	virtual void				AddNewLineAndHalf()				= 0;
	virtual void				AddDoubleNewLines()				= 0;
	virtual unsigned				GetFileFormatCounts()		= 0;
#ifdef _MFC_VER	// mfc specific code to follow
	virtual
	 const std::string&			GetClipStreamedText(unsigned i)	= 0;
#endif
	virtual
	 const std::string&			GetStreamedText(unsigned i)		= 0;

#ifdef _MFC_VER	// windows specific code
	bool						CopyToWord(CWnd* w);
	static void					ReleaseWordApp();
	bool						CopytoClipboard();
#endif

protected:
	// inlines
	unsigned						GetQueueLen() const;
	unsigned						GetTextSize() const;
	const std::string&			GetTextFont() const;
	void						SetInProgress(bool b);
	const std::string&			GetQueuedText();
	void						ClearQueuedText();

	// N.B. protected Data if a very bad idea and will lead to support problems later
	unsigned						CurrentFormat;

	// virtual functions: overrride to provide functionality
	virtual void				StreamQueuedText()				= 0;
	virtual void				DoBeginHeader()					= 0;
	virtual void				DoEndFooter()					= 0;
#ifdef _MFC_VER	// mfc specific code to follow
	virtual unsigned				GetClipboardFormat(unsigned i)		= 0;
#endif
	unsigned						Format_map_lookup(unsigned i);

private:
#ifdef _MFC_VER	// mfc specific code to follow
	static MSOfficeWord::_Application* pWordApp;
	static MSOfficeWord::_Application*	GetWordApp();
#endif
	int							TextSize;
	std::string					TextFont;
	bool						InProgress;
	std::string					QueuedText;

	typedef std::map<unsigned, unsigned> CMapUU;
	CMapUU						formats_map_lookup;
	unsigned						cnt_Formats;
	std::vector<CTextFormat>	vecFormats;
};

struct CFormattedOutput::CTextFormat
{
	CColourref	TextColour;
	CColourref	BackColour;
	bool		Italic;
	bool		Bold;
	void		Set(unsigned textCol, unsigned backCol = 0x00FFFFFF,
									bool it = false, bool bld = false);
	CTextFormat(){}
};

typedef std::vector<CFormattedOutput::CTextFormat>	CFormatVec;


//____________________________________________________________________________
//
//	CTextFormat inline
//
//____________________________________________________________________________

inline void CFormattedOutput::CTextFormat::Set(unsigned tCol, unsigned bCol, bool i, bool b)
{
	TextColour	= tCol;
	BackColour	= bCol;
	Italic		= i;
	Bold		= b;
}

//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
//
//	CFormattedOutput
//
//		inlines mainly for encapsulation
//
//888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
//_______________________________________________________________________________________
//
//	IsInProgress
//
//		flag to make sure that functions are not called out of sequence
//		Just a sanity check for the client code's convenience
//_______________________________________________________________________________________
inline bool CFormattedOutput::IsInProgress()
{
	return InProgress;
}
inline void CFormattedOutput::SetInProgress(bool b)
{
	InProgress = b;
}


inline unsigned CFormattedOutput::GetTextSize() const
{
	return TextSize;
}

inline const std::string&  CFormattedOutput::GetTextFont() const
{
	return TextFont;
}

inline unsigned CFormattedOutput::GetQueueLen() const
{
	return QueuedText.length();
}

inline const std::string& CFormattedOutput::GetQueuedText()
{
	return QueuedText;
}

inline void CFormattedOutput::ClearQueuedText()
{
	QueuedText.erase();
}

//		Queues text until the format changes or a new paragraph is added or EndHeader()
inline void CFormattedOutput::AddText(const std::string& s)	{QueuedText += s;}
inline void CFormattedOutput::AddText(char s)				{QueuedText += s;}
inline void CFormattedOutput::AddText(const std::string& s, unsigned pos, unsigned len)
															{QueuedText.append(s, pos, len);}

//_______________________________________________________________________________________
//
//	AddFormat, ClearFormats, GetFormat, GetFormatsCount
//
//		Adds to and removes and retrieves text formats from the table of formats
//		Last modified: lg 23/12/1999
//
//_______________________________________________________________________________________
inline void CFormattedOutput::AddFormats(const std::vector<CTextFormat>& vec)
{
	// should not add formats mid-stream
	assert(!InProgress);

	for (unsigned i = 0; i < vec.size(); ++i)
		AddFormat(vec[i]);
//	vecFormats = vec;
}

inline void CFormattedOutput::ClearFormats()
{
	// should not clear formats mid-stream
	assert(!InProgress);
	cnt_Formats = 0;
	formats_map_lookup.clear();
	vecFormats.clear();
//	vecFormats.clear();
}

inline unsigned CFormattedOutput::Format_map_lookup(unsigned i)
{
	assert(formats_map_lookup.find(i) != formats_map_lookup.end());
	return formats_map_lookup[i];
}

inline const CFormattedOutput::CTextFormat&	CFormattedOutput::GetFormat(unsigned i)
{
	unsigned vec_index = Format_map_lookup(i);

	// fail safe here
	assert(vec_index < vecFormats.size());
	if (vec_index >= vecFormats.size())
		vec_index = 0;

	return vecFormats[vec_index];
//	return vecFormats[i];
}

inline const std::vector<CFormattedOutput::CTextFormat>&	CFormattedOutput::GetFormatsTable()
{
	return vecFormats;
}

inline unsigned	CFormattedOutput::GetFormatsTableSize()
{
	return vecFormats.size();
}

inline unsigned CFormattedOutput::GetFormatsCount()
{
	return	cnt_Formats;
//	return vecFormats.size();
}




#endif // !defined(FORMATTEDOUTPUT_H)
